﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_OCF_Parser.h".
//-------------------------------------------------------------------

#ifndef _UXS_CONFIG_TYPES_H
#define _UXS_CONFIG_TYPES_H

#pragma once

#include "../MetaData/MetaData.h"

namespace UX_STL
{
namespace UXParser
{
	using namespace UXTypes;
	using namespace UXMetaTypes;

	
	namespace e_config_object
	{
		enum	type :	uint8
		{
			UNKNOWN		= 0,
			VALUE,
			STRING,
			ARRAY,
			BINARY_ARRAY,
			VARIANT_ARRAY,
			ENUM,
			OBJECT,
			NAMESPACE,
			CONSTANT,
			SCRIPT,
			USING,
		};
	}
	
	namespace e_config_event
	{
		enum	type :	uint8
		{
			OBJ_CREATE	= 0x01,

		};
	}

	class  CCfgBaseElement;
	struct TConfigObjConstructor;

	
	typedef tree< CCfgBaseElement *, TConfigObjConstructor >	config_tree_t;
	typedef config_tree_t::iterator								config_node_t;
	typedef config_tree_t::const_iterator						config_const_node_t;

	typedef bool (CALLBACK *POnCreateObjProc_t)(void *&pParam, void *pParameter);



	//
	// Config Base Element
	//

	class CCfgBaseElement
	{
	private:
		string							_sFieldName;
		config_node_t					_pNode;
		int								_iRefCount;
		const e_config_object::type		_eType;

	public:
		CCfgBaseElement(config_node_t pParent, e_config_object::type eType);
		virtual ~CCfgBaseElement();

		const string &			GetFieldName()	const	{ return _sFieldName; }
		e_config_object::type	GetType()		const	{ return _eType; }
		config_node_t			GetNode()		const	{ return _pNode; }
		
		bool Free();

		void SetName(uni_c_string pName)				{ _sFieldName = pName; }
		void SetName(string &sName)						{ _sFieldName.SetString( sName ); }

		void AddRef()									{ ++_iRefCount; }

		bool Copy(config_const_node_t pFields);
		bool CopyObj(config_const_node_t pFields);
		static void s_RecursiveCopyFields(config_node_t pNode, config_const_node_t pFields);
	};

	

	//
	// Config Object Tree Constructor
	//

	struct TConfigObjConstructor
	{
		static void CreateDefault(CCfgBaseElement *&e)					{ e = null; }
		static void Create(CCfgBaseElement *&e)							{}
		static void Destroy(CCfgBaseElement *&e)						{ if ( e != null ) e->Free(); }
		static void Copy(CCfgBaseElement *&from, CCfgBaseElement *&to)	{ to = from; }
	};



	//
	// Config Number Element (float, int | 8,16,32,64)
	//

	class CCfgNumberElem : public CCfgBaseElement
	{
	protected:
		union
		{
			double  _dValue;
			float   _fValue;
			int64   _i64Value;
			int32   _iValue;
			bool    _bValue;
			char    _aBuf[8];
		};
		e_value::type   _eValType;
		
	private:	
		bool _CopyValue(CCfgBaseElement *pObj, bool bInc = false);

	public:
		CCfgNumberElem(config_node_t pParent);
		CCfgNumberElem(config_node_t pParent, uni_c_string sValue, usize &uErrorPos);
		CCfgNumberElem(config_node_t pParent, CCfgBaseElement *pObj, bool bInc = false);
		CCfgNumberElem(const CCfgNumberElem &cObj, config_node_t pParent);
		~CCfgNumberElem();

		void SetValue(const void * pValue, e_value::type eValType);
		void SetDefault();

		void			GetValue(string &str)	const;
		const void *	GetValue()				const		{ return _aBuf; }
		e_value::type	GetValueType()			const		{ return _eValType; }
		int64			GetInt64()				const;
	};


	
	//
	// Config Object Element
	//

	class CCfgObjectElem : public CCfgBaseElement
	{
	protected:
		string					_sTypeName;
		uni_c_string_array_t	_aNamespaces;
		string					_sBindingName;
		const bool				_bInitList;

	public:
		CCfgObjectElem(config_node_t pParent, bool bInitList = true);
		CCfgObjectElem(config_node_t pParent, string &sType, uni_c_string_array_t &aNamespaces);
		CCfgObjectElem(const CCfgObjectElem &cObj, config_node_t pParent);
		CCfgObjectElem(config_node_t pParent, string &sName, e_config_object::type eType = e_config_object::NAMESPACE);
		~CCfgObjectElem();

		void SetBindingName(uni_c_string sName);

		bool						IsInitList()		const	{ return _bInitList; }
		const uni_c_string_array_t&	GetFullTypeName()	const	{ return _aNamespaces; }
		const string &				BindingName()		const	{ return _sBindingName; }
		const string &				GetTypeName()		const	{ return _sTypeName; }
	};



	//
	// Config Array Element
	//

	class CCfgArrayElem : public CCfgBaseElement
	{
	protected:
		string		_sTypeName;

	public:
		CCfgArrayElem(config_node_t pParent);
		~CCfgArrayElem();

		void SetTypeName(string &sTypeName)		{ _sTypeName.SetString( sTypeName ); }
		const string &	GetTypeName()	const	{ return _sTypeName; }
	};



	//
	// Config String Element
	//

	class CCfgStringElem : public CCfgBaseElement
	{
	protected:
		string			_sValue;

	public:
		CCfgStringElem(config_node_t pParent, string &sValue);
		CCfgStringElem(const CCfgStringElem &cObj, config_node_t pParent);
		~CCfgStringElem();
		
		bool SetValue(uni_c_string sValue);

		const string & GetStr()  const	{ return _sValue; }
		const char	 * GetCstr() const	{ return _sValue.cstr(); }
	};



	//
	// Config Script Element
	//

	class CCfgScriptElem : public CCfgBaseElement
	{
	public:
		CCfgScriptElem(config_node_t pParent);
	};
	


	//
	// Config Utils
	//

	class CCfgUtils
	{
	private:
		static void _RecursiveCopy(config_const_node_t pFrom, config_node_t pToNode);

	public:
		static bool CreateType(CCfgBaseElement *pObj, config_node_t pParent, CCfgBaseElement *&pNewObj);
		static bool Copy(config_const_node_t pFrom, config_node_t pToNode);
	};

//-------------------------------------------------------------------

}	// UXParser
}	// UX_STL

#endif	// _UXS_CONFIG_TYPES_H